/*-
 * Copyright (c) 2012 NetApp, Inc.
 * Copyright (c) 2015 xhyve developers
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

/*
 * xhyve ACPI table generator.
 *
 * Does not require iasl but DSDT is limited to 1 PCI bus (0) and 8 devices.
 *
 * slot 0 hostbridge
 * slot 31 lpc
 */

/*
 * The tables are placed in the guest's ROM area just below 1MB physical,
 * above the MPTable.
 *
 *  Layout
 *  ------
 *   RSDP  ->   0xf2400    (36 bytes fixed)
 *     RSDT  ->   0xf2440    (36 bytes + 4*7 table addrs, 4 used)
 *     XSDT  ->   0xf2480    (36 bytes + 8*7 table addrs, 4 used)
 *       MADT  ->   0xf2500  (depends on #CPUs)
 *       FADT  ->   0xf2600  (268 bytes)
 *       HPET  ->   0xf2740  (56 bytes)
 *       MCFG  ->   0xf2780  (60 bytes)
 *         FACS  ->   0xf27C0 (64 bytes)
 *         DSDT  ->   0xf2800 (variable - can go up to 0x100000)
 */

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <xhyve/support/misc.h>
#include <xhyve/vmm/vmm_api.h>
#include <xhyve/xhyve.h>
#include <xhyve/pci_emul.h>
#include <xhyve/acpi.h>

#define XHYVE_ACPI_BASE 0xf2400
#define XHYVE_ACPI_SIZE 0xdc00
#define RSDT_OFFSET 0x040
#define XSDT_OFFSET 0x080
#define MADT_OFFSET 0x100
#define FADT_OFFSET 0x200
#define HPET_OFFSET 0x340
#define MCFG_OFFSET 0x380
#define FACS_OFFSET 0x3C0
#define DSDT_OFFSET 0x400

/* ACPI table base in guest memory */
static void *tb;
static int acpi_ncpu;
static uint32_t hpet_capabilities;
static void *dsdt;

void
dsdt_line(UNUSED const char *fmt, ...)
{
}

void
dsdt_fixed_ioport(UNUSED uint16_t iobase, UNUSED uint16_t length)
{
}

void
dsdt_fixed_irq(UNUSED uint8_t irq)
{
}

void
dsdt_fixed_mem32(UNUSED uint32_t base, UNUSED uint32_t length)
{
}

void
dsdt_indent(UNUSED int levels)
{
}

void dsdt_unindent(UNUSED int levels)
{
}

static uint8_t
acpitbl_checksum(void *table, size_t length) {
	unsigned int i;
	uint8_t sum;

	for (sum = 0, i = 0; i < length; i++) {
		sum += ((uint8_t *) table)[i];
	}

	return (((uint8_t) 0) - sum);
}

static void
acpitbl_write8(void *base, uint64_t offset, uint8_t val) {
	memcpy(((void *) (((uintptr_t) base) + offset)), &val, 1);
}

static void
acpitbl_write16(void *base, uint64_t offset, uint16_t val) {
	memcpy(((void *) (((uintptr_t) base) + offset)), &val, 2);
}

static void
acpitbl_write32(void *base, uint64_t offset, uint32_t val) {
	memcpy(((void *) (((uintptr_t) base) + offset)), &val, 4);
}

static void
acpitbl_write64(void *base, uint64_t offset, uint64_t val) {
	memcpy(((void *) (((uintptr_t) base) + offset)), &val, 8);
}

static void
acpitbl_build_rdsp(void) {
	void *rdsp;
	/*
	 * [000h 0000  8]                    Signature : "RSD PTR "
	 * [008h 0008  1]                     Checksum : 00
	 * [009h 0009  6]                       Oem ID : "BHYVE "
	 * [00Fh 0015  1]                     Revision : 02
	 * [010h 0016  4]                 RSDT Address : 00000000
	 * [014h 0020  4]                       Length : 00000024
	 * [018h 0024  8]                 XSDT Address : 0000000000000000
	 * [020h 0032  1]            Extended Checksum : 00
	 * [021h 0033  3]                     Reserved : 000000
	 */
	static const uint8_t rdsp_tmpl[36] = {
		0x52, 0x53, 0x44, 0x20, 0x50, 0x54, 0x52, 0x20,
		0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20, 0x02,
		0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00
	};

	rdsp = (void *) (((uintptr_t) tb) + 0);
	/* copy RDSP template to guest memory */
	memcpy(rdsp, rdsp_tmpl, 36);
	/* fixup table */
	acpitbl_write32(rdsp, 0x10, ((uint32_t) (XHYVE_ACPI_BASE + RSDT_OFFSET)));
	acpitbl_write64(rdsp, 0x18, ((uint64_t) (XHYVE_ACPI_BASE + XSDT_OFFSET)));
	/* write checksum */
	acpitbl_write8(rdsp, 0x8, acpitbl_checksum(rdsp, 20));
	/* write extended checksum */
	acpitbl_write8(rdsp, 0x20, acpitbl_checksum(rdsp, 36));
}

static void
acpitbl_build_rsdt(void) {
	void *rsdt;
	/*
	 * [000h 0000  4]                    Signature : "RSDT"
	 * [004h 0004  4]                 Table Length : 00000034
	 * [008h 0008  1]                     Revision : 01
	 * [009h 0009  1]                     Checksum : 00
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVRSDT  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  4]       ACPI Table Address   0 : 00000000
	 * [028h 0040  4]       ACPI Table Address   1 : 00000000
	 * [02Ch 0044  4]       ACPI Table Address   2 : 00000000
	 * [030h 0048  4]       ACPI Table Address   3 : 00000000
	 */
	static const uint8_t rsdt_tmpl[52] = {
		0x52, 0x53, 0x44, 0x54, 0x34, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x52, 0x53, 0x44, 0x54, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00
	};

	rsdt = (void *) (((uintptr_t) tb) + RSDT_OFFSET);
	/* copy RSDT template to guest memory */
	memcpy(rsdt, rsdt_tmpl, 52);
	/* fixup table */
	acpitbl_write32(rsdt, 0x24, ((uint32_t) (XHYVE_ACPI_BASE + MADT_OFFSET)));
	acpitbl_write32(rsdt, 0x28, ((uint32_t) (XHYVE_ACPI_BASE + FADT_OFFSET)));
	acpitbl_write32(rsdt, 0x2c, ((uint32_t) (XHYVE_ACPI_BASE + HPET_OFFSET)));
	acpitbl_write32(rsdt, 0x30, ((uint32_t) (XHYVE_ACPI_BASE + MCFG_OFFSET)));
	/* write checksum */
	acpitbl_write8(rsdt, 0x9, acpitbl_checksum(rsdt, 52));
}

static void
acpitbl_build_xsdt(void) {
	void *xsdt;
	/*
	 * [000h 0000  4]                    Signature : "XSDT"
	 * [004h 0004  4]                 Table Length : 00000044
	 * [008h 0008  1]                     Revision : 01
	 * [009h 0009  1]                     Checksum : 00
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVXSDT  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  8]       ACPI Table Address   0 : 0000000000000000
	 * [02Ch 0044  8]       ACPI Table Address   1 : 0000000000000000
	 * [034h 0052  8]       ACPI Table Address   2 : 0000000000000000
	 * [03Ch 0060  8]       ACPI Table Address   3 : 0000000000000000
	 */
	static const uint8_t xsdt_tmpl[68] = {
  		0x58, 0x53, 0x44, 0x54, 0x44, 0x00, 0x00, 0x00,
  		0x01, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
  		0x42, 0x56, 0x58, 0x53, 0x44, 0x54, 0x20, 0x20,
  		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
  		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00,
  		0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00,
  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  		0x00, 0x00, 0x00, 0x00
	};

	xsdt = (void *) (((uintptr_t) tb) + XSDT_OFFSET);
	/* copy XSDT template to guest memory */
	memcpy(xsdt, xsdt_tmpl, 68);
	/* fixup table */
	acpitbl_write64(xsdt, 0x24, ((uint64_t) (XHYVE_ACPI_BASE + MADT_OFFSET)));
	acpitbl_write64(xsdt, 0x2c, ((uint64_t) (XHYVE_ACPI_BASE + FADT_OFFSET)));
	acpitbl_write64(xsdt, 0x34, ((uint64_t) (XHYVE_ACPI_BASE + HPET_OFFSET)));
	acpitbl_write64(xsdt, 0x3c, ((uint64_t) (XHYVE_ACPI_BASE + MCFG_OFFSET)));
	/* write checksum */
	acpitbl_write8(xsdt, 0x9, acpitbl_checksum(xsdt, 68));
}

static void
acpitbl_build_madt(void) {
	void *madt_head, *madt_apic, *madt_tail;
	int i;
	/*
	 * [000h 0000  4]                    Signature : "APIC"
	 * [004h 0004  4]                 Table Length : 00000000
	 * [008h 0008  1]                     Revision : 01
	 * [009h 0009  1]                     Checksum : 4E
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVMADT  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  4]           Local Apic Address : FEE00000
	 * [028h 0040  4]        Flags (decoded below) : 00000001
     *                         PC-AT Compatibility : 1
	 */
	static const uint8_t madt_head_tmpl[44] = {
		0x41, 0x50, 0x49, 0x43, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x4D, 0x41, 0x44, 0x54, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0xE0, 0xFE,
		0x01, 0x00, 0x00, 0x00,
	};
	/*
	 * [+000h +0000  1]              Subtable Type : 00 <Processor Local APIC>
	 * [+001h +0001  1]                     Length : 08
	 * [+002h +0002  1]               Processor ID : 00
	 * [+003h +0003  1]              Local Apic ID : 00
	 * [+004h +0004  4]      Flags (decoded below) : 00000001
	 *                           Processor Enabled : 1
	 */
	static const uint8_t madt_apic_tmpl[8] = {
		0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
	};
	/*
	 * [+000h +0000  1]              Subtable Type : 01 <I/O APIC>
	 * [+001h +0001  1]                     Length : 0C
	 * [+002h +0002  1]                I/O Apic ID : 00
	 * [+003h +0003  1]                   Reserved : 00
	 * [+004h +0004  4]                    Address : FEC00000
	 * [+008h +0008  4]                  Interrupt : 00000000
	 * [+00Ch +0012  1]              Subtable Type : 02 <IRQ Source Override>
	 * [+00Dh +0013  1]                     Length : 0A
	 * [+00Eh +0014  1]                        Bus : 00
	 * [+00Fh +0015  1]                     Source : 00
	 * [+010h +0016  4]                  Interrupt : 00000002
	 * [+014h +0020  2]      Flags (decoded below) : 0005
	 *                                  Polarity : 1
	 *                              Trigger Mode : 1
	 * [+016h +0022  1]              Subtable Type : 02 <IRQ Source Override>
	 * [+017h +0023  1]                     Length : 0A
	 * [+018h +0024  1]                        Bus : 00
	 * [+019h +0025  1]                     Source : 00
	 * [+01Ah +0026  4]                  Interrupt : 00000000
	 * [+01Eh +0030  2]      Flags (decoded below) : 000F
	 *                                  Polarity : 3
	 *                              Trigger Mode : 3
	 * [+020h +0032  1]              Subtable Type : 04 <Local APIC NMI>
	 * [+021h +0033  1]                     Length : 06
	 * [+022h +0034  1]               Processor ID : FF
	 * [+023h +0035  2]      Flags (decoded below) : 0005
	 *                                  Polarity : 1
	 *                              Trigger Mode : 1
	 * [+025h +0037  1]       Interrupt Input LINT : 01
	 */
	static const uint8_t madt_tail_tmpl[38] = {
		0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFE,
		0x00, 0x00, 0x00, 0x00, 0x02, 0x0A, 0x00, 0x00,
		0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x0A,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00,
		0x04, 0x06, 0xFF, 0x05, 0x00, 0x01
	};

	madt_head = (void *) (((uintptr_t) tb) + MADT_OFFSET);
	/* copy MADT head template to guest memory */
	memcpy(madt_head, madt_head_tmpl, 44);

	for (i = 0; i < acpi_ncpu; i++) {
		madt_apic = (void *) (((uintptr_t) tb)
			+ ((size_t) ((MADT_OFFSET + 44) + (8 * i))));
		/* copy MADT APIC template to guest memory */
		memcpy(madt_apic, madt_apic_tmpl, 8);
		/* fixup table */
		acpitbl_write8(madt_apic, 0x2, ((uint8_t) i));
		acpitbl_write8(madt_apic, 0x3, ((uint8_t) i));
	}

	madt_tail = (void *) (((uintptr_t) tb)
		+ ((size_t) ((MADT_OFFSET + 44) + (8 * acpi_ncpu))));
	/* copy MADT tail template to guest memory */
	memcpy(madt_tail, madt_tail_tmpl, 38);
	/* fixup table */
	acpitbl_write8(madt_tail, 0x2, 0);
	acpitbl_write8(madt_tail, 0x19, SCI_INT);
	acpitbl_write32(madt_tail, 0x1a, SCI_INT);
	/* write checksum */
	acpitbl_write32(madt_head, 0x4, ((uint32_t) (44 + (8 * acpi_ncpu) + 38)));
	acpitbl_write8(madt_head, 0x9,
		acpitbl_checksum(madt_head, ((size_t) (44 + (8 * acpi_ncpu) + 38))));
}

static void
acpitbl_build_fadt(void) {
	void *fadt;
	/*
	 * [000h 0000  4]                    Signature : "FACP"
	 * [004h 0004  4]                 Table Length : 0000010C
	 * [008h 0008  1]                     Revision : 05
	 * [009h 0009  1]                     Checksum : 00
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVFACP  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  4]                 FACS Address : 00000000
	 * [028h 0040  4]                 DSDT Address : 00000000
	 * [02Ch 0044  1]                        Model : 01
	 * [02Dh 0045  1]                   PM Profile : 00 (Unspecified)
	 * [02Eh 0046  2]                SCI Interrupt : 0000
	 * [030h 0048  4]             SMI Command Port : 00000000
	 * [034h 0052  1]            ACPI Enable Value : 00
	 * [035h 0053  1]           ACPI Disable Value : 00
	 * [036h 0054  1]               S4BIOS Command : 00
	 * [037h 0055  1]              P-State Control : 00
	 * [038h 0056  4]     PM1A Event Block Address : 00000000
	 * [03Ch 0060  4]     PM1B Event Block Address : 00000000
	 * [040h 0064  4]   PM1A Control Block Address : 00000000
	 * [044h 0068  4]   PM1B Control Block Address : 00000000
	 * [048h 0072  4]    PM2 Control Block Address : 00000000
	 * [04Ch 0076  4]       PM Timer Block Address : 00000000
	 * [050h 0080  4]           GPE0 Block Address : 00000000
	 * [054h 0084  4]           GPE1 Block Address : 00000000
	 * [058h 0088  1]       PM1 Event Block Length : 04
	 * [059h 0089  1]     PM1 Control Block Length : 02
	 * [05Ah 0090  1]     PM2 Control Block Length : 00
	 * [05Bh 0091  1]        PM Timer Block Length : 04
	 * [05Ch 0092  1]            GPE0 Block Length : 00
	 * [05Dh 0093  1]            GPE1 Block Length : 00
	 * [05Eh 0094  1]             GPE1 Base Offset : 00
	 * [05Fh 0095  1]                 _CST Support : 00
	 * [060h 0096  2]                   C2 Latency : 0000
	 * [062h 0098  2]                   C3 Latency : 0000
	 * [064h 0100  2]               CPU Cache Size : 0000
	 * [066h 0102  2]           Cache Flush Stride : 0000
	 * [068h 0104  1]            Duty Cycle Offset : 00
	 * [069h 0105  1]             Duty Cycle Width : 00
	 * [06Ah 0106  1]          RTC Day Alarm Index : 00
	 * [06Bh 0107  1]        RTC Month Alarm Index : 00
	 * [06Ch 0108  1]            RTC Century Index : 32
	 * [06Dh 0109  2]   Boot Flags (decoded below) : 0014
	 *               Legacy Devices Supported (V2) : 0
	 *            8042 Present on ports 60/64 (V2) : 0
	 *                        VGA Not Present (V4) : 1
	 *                      MSI Not Supported (V4) : 0
	 *                PCIe ASPM Not Supported (V4) : 1
	 * [06Fh 0111  1]                     Reserved : 00
	 * [070h 0112  4]        Flags (decoded below) : 00081525
	 *      WBINVD instruction is operational (V1) : 1
	 *              WBINVD flushes all caches (V1) : 0
	 *                    All CPUs support C1 (V1) : 1
	 *                  C2 works on MP system (V1) : 0
	 *            Control Method Power Button (V1) : 0
	 *            Control Method Sleep Button (V1) : 1
	 *        RTC wake not in fixed reg space (V1) : 0
	 *            RTC can wake system from S4 (V1) : 0
	 *                        32-bit PM Timer (V1) : 1
	 *                      Docking Supported (V1) : 0
	 *               Reset Register Supported (V2) : 1
	 *                            Sealed Case (V3) : 0
	 *                    Headless - No Video (V3) : 1
	 *        Use native instr after SLP_TYPx (V3) : 0
	 *              PCIEXP_WAK Bits Supported (V4) : 0
	 *                     Use Platform Timer (V4) : 0
	 *               RTC_STS valid on S4 wake (V4) : 0
	 *                Remote Power-on capable (V4) : 0
	 *                 Use APIC Cluster Model (V4) : 0
	 *     Use APIC Physical Destination Mode (V4) : 1
	 * [074h 0116 12]               Reset Register : <Generic Address Structure>
	 * [074h 0116  1]                     Space ID : 01 (SystemIO)
	 * [075h 0117  1]                    Bit Width : 08
	 * [076h 0118  1]                   Bit Offset : 00
	 * [077h 0119  1]                 Access Width : 01
	 * [078h 0120  8]                      Address : 0000000000000CF9
	 * [080h 0128  1]         Value to cause reset : 06
	 * [081h 0129  3]                     Reserved : 000001
	 * [084h 0132  8]                 FACS Address : 0000000000000000
	 * [08Ch 0140  8]                 DSDT Address : 0000000000000000
	 * [094h 0148 12]             PM1A Event Block : <Generic Address Structure>
	 * [094h 0148  1]                     Space ID : 01 (SystemIO)
	 * [095h 0149  1]                    Bit Width : 20
	 * [096h 0150  1]                   Bit Offset : 00
	 * [097h 0151  1]                 Access Width : 02
	 * [098h 0152  8]                      Address : 0000000000000000
	 * [0A0h 0160 12]             PM1B Event Block : <Generic Address Structure>
	 * [0A0h 0160  1]                     Space ID : 01 (SystemIO)
	 * [0A1h 0161  1]                    Bit Width : 00
	 * [0A2h 0162  1]                   Bit Offset : 00
	 * [0A3h 0163  1]                 Access Width : 00
	 * [0A4h 0164  8]                      Address : 0000000000000000
	 * [0ACh 0172 12]           PM1A Control Block : <Generic Address Structure>
	 * [0ACh 0172  1]                     Space ID : 01 (SystemIO)
	 * [0ADh 0173  1]                    Bit Width : 10
	 * [0AEh 0174  1]                   Bit Offset : 00
	 * [0AFh 0175  1]                 Access Width : 02
	 * [0B0h 0176  8]                      Address : 0000000000000000
	 * [0B8h 0184 12]           PM1B Control Block : <Generic Address Structure>
	 * [0B8h 0184  1]                     Space ID : 01 (SystemIO)
	 * [0B9h 0185  1]                    Bit Width : 00
	 * [0BAh 0186  1]                   Bit Offset : 00
	 * [0BBh 0187  1]                 Access Width : 00
	 * [0BCh 0188  8]                      Address : 0000000000000000
	 * [0C4h 0196 12]            PM2 Control Block : <Generic Address Structure>
	 * [0C4h 0196  1]                     Space ID : 01 (SystemIO)
	 * [0C5h 0197  1]                    Bit Width : 08
	 * [0C6h 0198  1]                   Bit Offset : 00
	 * [0C7h 0199  1]                 Access Width : 00
	 * [0C8h 0200  8]                      Address : 0000000000000000
	 * [0D0h 0208 12]               PM Timer Block : <Generic Address Structure>
	 * [0D0h 0208  1]                     Space ID : 01 (SystemIO)
	 * [0D1h 0209  1]                    Bit Width : 20
	 * [0D2h 0210  1]                   Bit Offset : 00
	 * [0D3h 0211  1]                 Access Width : 03
	 * [0D4h 0212  8]                      Address : 0000000000000000
	 * [0DCh 0220 12]                   GPE0 Block : <Generic Address Structure>
	 * [0DCh 0220  1]                     Space ID : 01 (SystemIO)
	 * [0DDh 0221  1]                    Bit Width : 00
	 * [0DEh 0222  1]                   Bit Offset : 00
	 * [0DFh 0223  1]                 Access Width : 01
	 * [0E0h 0224  8]                      Address : 0000000000000000
	 * [0E8h 0232 12]                   GPE1 Block : <Generic Address Structure>
	 * [0E8h 0232  1]                     Space ID : 01 (SystemIO)
	 * [0E9h 0233  1]                    Bit Width : 00
	 * [0EAh 0234  1]                   Bit Offset : 00
	 * [0EBh 0235  1]                 Access Width : 00
	 * [0ECh 0236  8]                      Address : 0000000000000000
	 * [0F4h 0244 12]       Sleep Control Register : <Generic Address Structure>
	 * [0F4h 0244  1]                     Space ID : 01 (SystemIO)
	 * [0F5h 0245  1]                    Bit Width : 08
	 * [0F6h 0246  1]                   Bit Offset : 00
	 * [0F7h 0247  1]                 Access Width : 01
	 * [0F8h 0248  8]                      Address : 0000000000000000
	 * [100h 0256 12]        Sleep Status Register : <Generic Address Structure>
	 * [100h 0256 01]                     Space ID : 01 (SystemIO)
	 * [101h 0257 01]                    Bit Width : 08
	 * [102h 0258 01]                   Bit Offset : 00
	 * [103h 0259 01]                 Access Width : 01
	 * [104h 0260 08]                      Address : 0000000000000000
	 */
	static const uint8_t fadt_tmpl[268] = {
		0x46, 0x41, 0x43, 0x50, 0x0C, 0x01, 0x00, 0x00,
		0x05, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x46, 0x41, 0x43, 0x50, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x04, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x32, 0x14, 0x00, 0x00,
		0x25, 0x15, 0x08, 0x00, 0x01, 0x08, 0x00, 0x01,
		0xF9, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x02,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x02,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x01,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x01, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00
	};

	fadt = (void *) (((uintptr_t) tb) + FADT_OFFSET);
	/* copy FADT template to guest memory */
	memcpy(fadt, fadt_tmpl, 268);
	/* fixup table */
	acpitbl_write32(fadt, 0x24, ((uint32_t) (XHYVE_ACPI_BASE + FACS_OFFSET)));
	acpitbl_write32(fadt, 0x28, ((uint32_t) (XHYVE_ACPI_BASE + DSDT_OFFSET)));
	acpitbl_write16(fadt, 0x2e, SCI_INT);
	acpitbl_write32(fadt, 0x30, SMI_CMD);
	acpitbl_write8(fadt, 0x34, BHYVE_ACPI_ENABLE);
	acpitbl_write8(fadt, 0x35, BHYVE_ACPI_DISABLE);
	acpitbl_write32(fadt, 0x38, PM1A_EVT_ADDR);
	acpitbl_write32(fadt, 0x40, PM1A_CNT_ADDR);
	acpitbl_write32(fadt, 0x4c, IO_PMTMR);
	acpitbl_write64(fadt, 0x84, ((uint64_t) (XHYVE_ACPI_BASE + FACS_OFFSET)));
	acpitbl_write64(fadt, 0x8c, ((uint64_t) (XHYVE_ACPI_BASE + DSDT_OFFSET)));
	acpitbl_write64(fadt, 0x98, ((uint64_t) PM1A_EVT_ADDR));
	acpitbl_write64(fadt, 0xb0, ((uint64_t) PM1A_CNT_ADDR));
	acpitbl_write64(fadt, 0xd4, ((uint64_t) IO_PMTMR));
	/* write checksum */
	acpitbl_write8(fadt, 0x9, acpitbl_checksum(fadt, 268));
}

static void
acpitbl_build_hpet(void) {
	void *hpet;
	/*
	 * [000h 0000  4]                    Signature : "HPET"
	 * [004h 0004  4]                 Table Length : 00000038
	 * [008h 0008  1]                     Revision : 01
	 * [009h 0009  1]                     Checksum : 00
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVHPET  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  4]            Hardware Block ID : 00000000
	 * [028h 0040 12]         Timer Block Register : <Generic Address Structure>
	 * [028h 0040  1]                     Space ID : 00 (SystemMemory)
	 * [029h 0041  1]                    Bit Width : 00
	 * [02Ah 0042  1]                   Bit Offset : 00
	 * [02Bh 0043  1]                 Access Width : 00
	 * [02Ch 0044  8]                      Address : 00000000FED00000
	 * [034h 0052  1]              Sequence Number : 00
	 * [035h 0053  2]          Minimum Clock Ticks : 0000
	 * [037h 0055  1]        Flags (decoded below) : 01
	 *                             4K Page Protect : 1
	 *                            64K Page Protect : 0
	 */
	static const uint8_t hpet_tmpl[56] = {
		0x48, 0x50, 0x45, 0x54, 0x38, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x48, 0x50, 0x45, 0x54, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFE,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
	};

	hpet = (void *) (((uintptr_t) tb) + HPET_OFFSET);
	/* copy HPET template to guest memory */
	memcpy(hpet, hpet_tmpl, 56);
	/* fixup table */
	acpitbl_write32(hpet, 0x24, hpet_capabilities);
	/* write checksum */
	acpitbl_write8(hpet, 0x9, acpitbl_checksum(hpet, 56));
}

static void
acpitbl_build_mcfg(void) {
	void *mcfg;
	/*
	 * [000h 0000  4]                    Signature : "MCFG"
	 * [004h 0004  4]                 Table Length : 0000003C
	 * [008h 0008  1]                     Revision : 01
	 * [009h 0009  1]                     Checksum : 00
	 * [00Ah 0010  6]                       Oem ID : "BHYVE "
	 * [010h 0016  8]                 Oem Table ID : "BVMCFG  "
	 * [018h 0024  4]                 Oem Revision : 00000001
	 * [01Ch 0028  4]              Asl Compiler ID : "INTL"
	 * [020h 0032  4]        Asl Compiler Revision : 20140828
	 * [024h 0036  8]                     Reserved : 0000000000000000
	 * [02Ch 0044  8]                 Base Address : 0000000000000000
	 * [034h 0052  2]         Segment Group Number : 0000
	 * [036h 0054  1]             Start Bus Number : 00
	 * [037h 0055  1]               End Bus Number : FF
	 * [038h 0056  4]                     Reserved : 00000000
	 */
	static const uint8_t mcfg_tmpl[60] = {
		0x4D, 0x43, 0x46, 0x47, 0x3C, 0x00, 0x00, 0x00,
		0x01, 0x00, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x4D, 0x43, 0x46, 0x47, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
		0x28, 0x08, 0x14, 0x20, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
		0x00, 0x00, 0x00, 0x00
	};

	mcfg = (void *) (((uintptr_t) tb) + MCFG_OFFSET);
	/* copy MCFG template to guest memory */
	memcpy(mcfg, mcfg_tmpl, 60);
	/* fixup table */
	acpitbl_write64(mcfg, 0x2c, pci_ecfg_base());
	/* write checksum */
	acpitbl_write8(mcfg, 0x9, acpitbl_checksum(mcfg, 60));
}

static void
acpitbl_build_facs(void) {
	void *facs;
	/*
	 * [000h 0000  4]                    Signature : "FACS"
	 * [004h 0004  4]                       Length : 00000040
	 * [008h 0008  4]           Hardware Signature : 00000000
	 * [00Ch 0012  4]    32 Firmware Waking Vector : 00000000
	 * [010h 0016  4]                  Global Lock : 00000000
	 * [014h 0020  4]        Flags (decoded below) : 00000000
	 *                      S4BIOS Support Present : 0
	 *                  64-bit Wake Supported (V2) : 0
	 * [018h 0024  8]    64 Firmware Waking Vector : 0000000000000000
	 * [020h 0032  1]                      Version : 02
	 * [021h 0033  3]                     Reserved : 000000
	 * [024h 0036  4]    OspmFlags (decoded below) : 00000000
	 *               64-bit Wake Env Required (V2) : 0
	 */
	static const uint8_t facs_tmpl[64] = {
		0x46, 0x41, 0x43, 0x53, 0x40, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};

	facs = (void *) (((uintptr_t) tb) + FACS_OFFSET);
	/* copy MCFG template to guest memory */
	memcpy(facs, facs_tmpl, 64);
}

void dsdt_fixup(int bus, uint16_t iobase, uint16_t iolimit, uint32_t membase32,
	uint32_t memlimit32, uint64_t membase64, uint64_t memlimit64)
{
	if (bus != 0) {
		fprintf(stderr, "DSDT, unsupported PCI bus (%d)\n", bus);
		exit(-1);
	}

	acpitbl_write16(dsdt, 0xb6, iobase);
	acpitbl_write16(dsdt, 0xb8, (iolimit - 1));
	acpitbl_write16(dsdt, 0xbc, (iolimit - iobase));
	acpitbl_write32(dsdt, 0xc8, membase32);
	acpitbl_write32(dsdt, 0xcc, (memlimit32 - 1));
	acpitbl_write32(dsdt, 0xd4, (memlimit32 - membase32));
	acpitbl_write64(dsdt, 0xe6, membase64);
	acpitbl_write64(dsdt, 0xee, (memlimit64 - 1));
	acpitbl_write64(dsdt, 0xfe, (memlimit64 - membase64));
}

static void
acpitbl_build_dsdt(void) {
	static const uint8_t dsdt_tmpl[2604] = {
		0x44, 0x53, 0x44, 0x54, 0x2d, 0x0a, 0x00, 0x00,
		0x02, 0x5d, 0x42, 0x48, 0x59, 0x56, 0x45, 0x20,
		0x42, 0x56, 0x44, 0x53, 0x44, 0x54, 0x20, 0x20,
		0x01, 0x00, 0x00, 0x00, 0x49, 0x4e, 0x54, 0x4c,
		0x28, 0x08, 0x14, 0x20, 0x08, 0x5f, 0x53, 0x35,
		0x5f, 0x12, 0x05, 0x02, 0x0a, 0x05, 0x00, 0x08,
		0x50, 0x49, 0x43, 0x4d, 0x0a, 0x00, 0x14, 0x0c,
		0x5f, 0x50, 0x49, 0x43, 0x01, 0x70, 0x68, 0x50,
		0x49, 0x43, 0x4d, 0x10, 0x4f, 0x9a, 0x5f, 0x53,
		0x42, 0x5f, 0x5b, 0x82, 0x47, 0x9a, 0x50, 0x43,
		0x30, 0x30, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c,
		0x41, 0xd0, 0x0a, 0x03, 0x08, 0x5f, 0x41, 0x44,
		0x52, 0x00, 0x14, 0x09, 0x5f, 0x42, 0x42, 0x4e,
		0x00, 0xa4, 0x0a, 0x00, 0x08, 0x5f, 0x43, 0x52,
		0x53, 0x11, 0x46, 0x09, 0x0a, 0x92, 0x88, 0x0d,
		0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x47, 0x01,
		0xf8, 0x0c, 0xf8, 0x0c, 0x01, 0x08, 0x88, 0x0d,
		0x00, 0x01, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00,
		0xf7, 0x0c, 0x00, 0x00, 0xf8, 0x0c, 0x88, 0x0d,
		0x00, 0x01, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x0d,
		0xff, 0x1f, 0x00, 0x00, 0x00, 0x13, 0x88, 0x0d,
		0x00, 0x01, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x20,
		0x1f, 0x20, 0x00, 0x00, 0x20, 0x00, 0x87, 0x17,
		0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0xc0,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
		0x8a, 0x2b, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
		0x0f, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x10, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x79, 0x00,
		0x08, 0x50, 0x50, 0x52, 0x54, 0x12, 0x4b, 0x0f,
		0x08, 0x12, 0x1e, 0x04, 0x0c, 0xff, 0xff, 0x01,
		0x00, 0x0a, 0x00, 0x5c, 0x2f, 0x04, 0x5f, 0x53,
		0x42, 0x5f, 0x50, 0x43, 0x30, 0x30, 0x49, 0x53,
		0x41, 0x5f, 0x4c, 0x4e, 0x4b, 0x41, 0x0a, 0x00,
		0x12, 0x1e, 0x04, 0x0c, 0xff, 0xff, 0x02, 0x00,
		0x0a, 0x00, 0x5c, 0x2f, 0x04, 0x5f, 0x53, 0x42,
		0x5f, 0x50, 0x43, 0x30, 0x30, 0x49, 0x53, 0x41,
		0x5f, 0x4c, 0x4e, 0x4b, 0x42, 0x0a, 0x00, 0x12,
		0x1e, 0x04, 0x0c, 0xff, 0xff, 0x03, 0x00, 0x0a,
		0x00, 0x5c, 0x2f, 0x04, 0x5f, 0x53, 0x42, 0x5f,
		0x50, 0x43, 0x30, 0x30, 0x49, 0x53, 0x41, 0x5f,
		0x4c, 0x4e, 0x4b, 0x43, 0x0a, 0x00, 0x12, 0x1e,
		0x04, 0x0c, 0xff, 0xff, 0x04, 0x00, 0x0a, 0x00,
		0x5c, 0x2f, 0x04, 0x5f, 0x53, 0x42, 0x5f, 0x50,
		0x43, 0x30, 0x30, 0x49, 0x53, 0x41, 0x5f, 0x4c,
		0x4e, 0x4b, 0x44, 0x0a, 0x00, 0x12, 0x1e, 0x04,
		0x0c, 0xff, 0xff, 0x05, 0x00, 0x0a, 0x00, 0x5c,
		0x2f, 0x04, 0x5f, 0x53, 0x42, 0x5f, 0x50, 0x43,
		0x30, 0x30, 0x49, 0x53, 0x41, 0x5f, 0x4c, 0x4e,
		0x4b, 0x45, 0x0a, 0x00, 0x12, 0x1e, 0x04, 0x0c,
		0xff, 0xff, 0x06, 0x00, 0x0a, 0x00, 0x5c, 0x2f,
		0x04, 0x5f, 0x53, 0x42, 0x5f, 0x50, 0x43, 0x30,
		0x30, 0x49, 0x53, 0x41, 0x5f, 0x4c, 0x4e, 0x4b,
		0x46, 0x0a, 0x00, 0x12, 0x1e, 0x04, 0x0c, 0xff,
		0xff, 0x07, 0x00, 0x0a, 0x00, 0x5c, 0x2f, 0x04,
		0x5f, 0x53, 0x42, 0x5f, 0x50, 0x43, 0x30, 0x30,
		0x49, 0x53, 0x41, 0x5f, 0x4c, 0x4e, 0x4b, 0x47,
		0x0a, 0x00, 0x12, 0x1e, 0x04, 0x0c, 0xff, 0xff,
		0x08, 0x00, 0x0a, 0x00, 0x5c, 0x2f, 0x04, 0x5f,
		0x53, 0x42, 0x5f, 0x50, 0x43, 0x30, 0x30, 0x49,
		0x53, 0x41, 0x5f, 0x4c, 0x4e, 0x4b, 0x48, 0x0a,
		0x00, 0x08, 0x41, 0x50, 0x52, 0x54, 0x12, 0x4b,
		0x06, 0x08, 0x12, 0x0c, 0x04, 0x0c, 0xff, 0xff,
		0x01, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x10, 0x12,
		0x0c, 0x04, 0x0c, 0xff, 0xff, 0x02, 0x00, 0x0a,
		0x00, 0x00, 0x0a, 0x11, 0x12, 0x0c, 0x04, 0x0c,
		0xff, 0xff, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x0a,
		0x12, 0x12, 0x0c, 0x04, 0x0c, 0xff, 0xff, 0x04,
		0x00, 0x0a, 0x00, 0x00, 0x0a, 0x13, 0x12, 0x0c,
		0x04, 0x0c, 0xff, 0xff, 0x05, 0x00, 0x0a, 0x00,
		0x00, 0x0a, 0x14, 0x12, 0x0c, 0x04, 0x0c, 0xff,
		0xff, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x15,
		0x12, 0x0c, 0x04, 0x0c, 0xff, 0xff, 0x07, 0x00,
		0x0a, 0x00, 0x00, 0x0a, 0x16, 0x12, 0x0c, 0x04,
		0x0c, 0xff, 0xff, 0x08, 0x00, 0x0a, 0x00, 0x00,
		0x0a, 0x17, 0x14, 0x18, 0x5f, 0x50, 0x52, 0x54,
		0x00, 0xa0, 0x0a, 0x50, 0x49, 0x43, 0x4d, 0xa4,
		0x41, 0x50, 0x52, 0x54, 0xa1, 0x06, 0xa4, 0x50,
		0x50, 0x52, 0x54, 0x5b, 0x82, 0x4e, 0x75, 0x49,
		0x53, 0x41, 0x5f, 0x08, 0x5f, 0x41, 0x44, 0x52,
		0x0c, 0x00, 0x00, 0x1f, 0x00, 0x5b, 0x80, 0x4c,
		0x50, 0x43, 0x52, 0x02, 0x0a, 0x00, 0x0b, 0x00,
		0x01, 0x5b, 0x81, 0x33, 0x4c, 0x50, 0x43, 0x52,
		0x00, 0x00, 0x40, 0x30, 0x50, 0x49, 0x52, 0x41,
		0x08, 0x50, 0x49, 0x52, 0x42, 0x08, 0x50, 0x49,
		0x52, 0x43, 0x08, 0x50, 0x49, 0x52, 0x44, 0x08,
		0x00, 0x20, 0x50, 0x49, 0x52, 0x45, 0x08, 0x50,
		0x49, 0x52, 0x46, 0x08, 0x50, 0x49, 0x52, 0x47,
		0x08, 0x50, 0x49, 0x52, 0x48, 0x08, 0x14, 0x33,
		0x50, 0x49, 0x52, 0x56, 0x01, 0xa0, 0x09, 0x7b,
		0x68, 0x0a, 0x80, 0x00, 0xa4, 0x0a, 0x00, 0x7b,
		0x68, 0x0a, 0x0f, 0x60, 0xa0, 0x08, 0x95, 0x60,
		0x0a, 0x03, 0xa4, 0x0a, 0x00, 0xa0, 0x08, 0x93,
		0x60, 0x0a, 0x08, 0xa4, 0x0a, 0x00, 0xa0, 0x08,
		0x93, 0x60, 0x0a, 0x0d, 0xa4, 0x0a, 0x00, 0xa4,
		0x0a, 0x01, 0x5b, 0x82, 0x4f, 0x0a, 0x4c, 0x4e,
		0x4b, 0x41, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c,
		0x41, 0xd0, 0x0c, 0x0f, 0x08, 0x5f, 0x55, 0x49,
		0x44, 0x0a, 0x01, 0x14, 0x18, 0x5f, 0x53, 0x54,
		0x41, 0x00, 0xa0, 0x0c, 0x50, 0x49, 0x52, 0x56,
		0x50, 0x49, 0x52, 0x41, 0xa4, 0x0a, 0x0b, 0xa1,
		0x04, 0xa4, 0x0a, 0x09, 0x08, 0x5f, 0x50, 0x52,
		0x53, 0x11, 0x09, 0x0a, 0x06, 0x23, 0xf8, 0xde,
		0x18, 0x79, 0x00, 0x08, 0x43, 0x42, 0x30, 0x31,
		0x11, 0x09, 0x0a, 0x06, 0x23, 0x00, 0x00, 0x18,
		0x79, 0x00, 0x8b, 0x43, 0x42, 0x30, 0x31, 0x0a,
		0x01, 0x43, 0x49, 0x52, 0x41, 0x14, 0x2b, 0x5f,
		0x43, 0x52, 0x53, 0x00, 0x7b, 0x50, 0x49, 0x52,
		0x41, 0x0a, 0x8f, 0x60, 0xa0, 0x0e, 0x50, 0x49,
		0x52, 0x56, 0x60, 0x79, 0x0a, 0x01, 0x60, 0x43,
		0x49, 0x52, 0x41, 0xa1, 0x08, 0x70, 0x0a, 0x00,
		0x43, 0x49, 0x52, 0x41, 0xa4, 0x43, 0x42, 0x30,
		0x31, 0x14, 0x0d, 0x5f, 0x44, 0x49, 0x53, 0x00,
		0x70, 0x0a, 0x80, 0x50, 0x49, 0x52, 0x41, 0x14,
		0x1b, 0x5f, 0x53, 0x52, 0x53, 0x01, 0x8b, 0x68,
		0x0a, 0x01, 0x53, 0x49, 0x52, 0x41, 0x82, 0x53,
		0x49, 0x52, 0x41, 0x60, 0x70, 0x76, 0x60, 0x50,
		0x49, 0x52, 0x41, 0x5b, 0x82, 0x4f, 0x0a, 0x4c,
		0x4e, 0x4b, 0x42, 0x08, 0x5f, 0x48, 0x49, 0x44,
		0x0c, 0x41, 0xd0, 0x0c, 0x0f, 0x08, 0x5f, 0x55,
		0x49, 0x44, 0x0a, 0x02, 0x14, 0x18, 0x5f, 0x53,
		0x54, 0x41, 0x00, 0xa0, 0x0c, 0x50, 0x49, 0x52,
		0x56, 0x50, 0x49, 0x52, 0x42, 0xa4, 0x0a, 0x0b,
		0xa1, 0x04, 0xa4, 0x0a, 0x09, 0x08, 0x5f, 0x50,
		0x52, 0x53, 0x11, 0x09, 0x0a, 0x06, 0x23, 0xf8,
		0xde, 0x18, 0x79, 0x00, 0x08, 0x43, 0x42, 0x30,
		0x32, 0x11, 0x09, 0x0a, 0x06, 0x23, 0x00, 0x00,
		0x18, 0x79, 0x00, 0x8b, 0x43, 0x42, 0x30, 0x32,
		0x0a, 0x01, 0x43, 0x49, 0x52, 0x42, 0x14, 0x2b,
		0x5f, 0x43, 0x52, 0x53, 0x00, 0x7b, 0x50, 0x49,
		0x52, 0x42, 0x0a, 0x8f, 0x60, 0xa0, 0x0e, 0x50,
		0x49, 0x52, 0x56, 0x60, 0x79, 0x0a, 0x01, 0x60,
		0x43, 0x49, 0x52, 0x42, 0xa1, 0x08, 0x70, 0x0a,
		0x00, 0x43, 0x49, 0x52, 0x42, 0xa4, 0x43, 0x42,
		0x30, 0x32, 0x14, 0x0d, 0x5f, 0x44, 0x49, 0x53,
		0x00, 0x70, 0x0a, 0x80, 0x50, 0x49, 0x52, 0x42,
		0x14, 0x1b, 0x5f, 0x53, 0x52, 0x53, 0x01, 0x8b,
		0x68, 0x0a, 0x01, 0x53, 0x49, 0x52, 0x42, 0x82,
		0x53, 0x49, 0x52, 0x42, 0x60, 0x70, 0x76, 0x60,
		0x50, 0x49, 0x52, 0x42, 0x5b, 0x82, 0x4f, 0x0a,
		0x4c, 0x4e, 0x4b, 0x43, 0x08, 0x5f, 0x48, 0x49,
		0x44, 0x0c, 0x41, 0xd0, 0x0c, 0x0f, 0x08, 0x5f,
		0x55, 0x49, 0x44, 0x0a, 0x03, 0x14, 0x18, 0x5f,
		0x53, 0x54, 0x41, 0x00, 0xa0, 0x0c, 0x50, 0x49,
		0x52, 0x56, 0x50, 0x49, 0x52, 0x43, 0xa4, 0x0a,
		0x0b, 0xa1, 0x04, 0xa4, 0x0a, 0x09, 0x08, 0x5f,
		0x50, 0x52, 0x53, 0x11, 0x09, 0x0a, 0x06, 0x23,
		0xf8, 0xde, 0x18, 0x79, 0x00, 0x08, 0x43, 0x42,
		0x30, 0x33, 0x11, 0x09, 0x0a, 0x06, 0x23, 0x00,
		0x00, 0x18, 0x79, 0x00, 0x8b, 0x43, 0x42, 0x30,
		0x33, 0x0a, 0x01, 0x43, 0x49, 0x52, 0x43, 0x14,
		0x2b, 0x5f, 0x43, 0x52, 0x53, 0x00, 0x7b, 0x50,
		0x49, 0x52, 0x43, 0x0a, 0x8f, 0x60, 0xa0, 0x0e,
		0x50, 0x49, 0x52, 0x56, 0x60, 0x79, 0x0a, 0x01,
		0x60, 0x43, 0x49, 0x52, 0x43, 0xa1, 0x08, 0x70,
		0x0a, 0x00, 0x43, 0x49, 0x52, 0x43, 0xa4, 0x43,
		0x42, 0x30, 0x33, 0x14, 0x0d, 0x5f, 0x44, 0x49,
		0x53, 0x00, 0x70, 0x0a, 0x80, 0x50, 0x49, 0x52,
		0x43, 0x14, 0x1b, 0x5f, 0x53, 0x52, 0x53, 0x01,
		0x8b, 0x68, 0x0a, 0x01, 0x53, 0x49, 0x52, 0x43,
		0x82, 0x53, 0x49, 0x52, 0x43, 0x60, 0x70, 0x76,
		0x60, 0x50, 0x49, 0x52, 0x43, 0x5b, 0x82, 0x4f,
		0x0a, 0x4c, 0x4e, 0x4b, 0x44, 0x08, 0x5f, 0x48,
		0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0c, 0x0f, 0x08,
		0x5f, 0x55, 0x49, 0x44, 0x0a, 0x04, 0x14, 0x18,
		0x5f, 0x53, 0x54, 0x41, 0x00, 0xa0, 0x0c, 0x50,
		0x49, 0x52, 0x56, 0x50, 0x49, 0x52, 0x44, 0xa4,
		0x0a, 0x0b, 0xa1, 0x04, 0xa4, 0x0a, 0x09, 0x08,
		0x5f, 0x50, 0x52, 0x53, 0x11, 0x09, 0x0a, 0x06,
		0x23, 0xf8, 0xde, 0x18, 0x79, 0x00, 0x08, 0x43,
		0x42, 0x30, 0x34, 0x11, 0x09, 0x0a, 0x06, 0x23,
		0x00, 0x00, 0x18, 0x79, 0x00, 0x8b, 0x43, 0x42,
		0x30, 0x34, 0x0a, 0x01, 0x43, 0x49, 0x52, 0x44,
		0x14, 0x2b, 0x5f, 0x43, 0x52, 0x53, 0x00, 0x7b,
		0x50, 0x49, 0x52, 0x44, 0x0a, 0x8f, 0x60, 0xa0,
		0x0e, 0x50, 0x49, 0x52, 0x56, 0x60, 0x79, 0x0a,
		0x01, 0x60, 0x43, 0x49, 0x52, 0x44, 0xa1, 0x08,
		0x70, 0x0a, 0x00, 0x43, 0x49, 0x52, 0x44, 0xa4,
		0x43, 0x42, 0x30, 0x34, 0x14, 0x0d, 0x5f, 0x44,
		0x49, 0x53, 0x00, 0x70, 0x0a, 0x80, 0x50, 0x49,
		0x52, 0x44, 0x14, 0x1b, 0x5f, 0x53, 0x52, 0x53,
		0x01, 0x8b, 0x68, 0x0a, 0x01, 0x53, 0x49, 0x52,
		0x44, 0x82, 0x53, 0x49, 0x52, 0x44, 0x60, 0x70,
		0x76, 0x60, 0x50, 0x49, 0x52, 0x44, 0x5b, 0x82,
		0x4f, 0x0a, 0x4c, 0x4e, 0x4b, 0x45, 0x08, 0x5f,
		0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0c, 0x0f,
		0x08, 0x5f, 0x55, 0x49, 0x44, 0x0a, 0x05, 0x14,
		0x18, 0x5f, 0x53, 0x54, 0x41, 0x00, 0xa0, 0x0c,
		0x50, 0x49, 0x52, 0x56, 0x50, 0x49, 0x52, 0x45,
		0xa4, 0x0a, 0x0b, 0xa1, 0x04, 0xa4, 0x0a, 0x09,
		0x08, 0x5f, 0x50, 0x52, 0x53, 0x11, 0x09, 0x0a,
		0x06, 0x23, 0xf8, 0xde, 0x18, 0x79, 0x00, 0x08,
		0x43, 0x42, 0x30, 0x35, 0x11, 0x09, 0x0a, 0x06,
		0x23, 0x00, 0x00, 0x18, 0x79, 0x00, 0x8b, 0x43,
		0x42, 0x30, 0x35, 0x0a, 0x01, 0x43, 0x49, 0x52,
		0x45, 0x14, 0x2b, 0x5f, 0x43, 0x52, 0x53, 0x00,
		0x7b, 0x50, 0x49, 0x52, 0x45, 0x0a, 0x8f, 0x60,
		0xa0, 0x0e, 0x50, 0x49, 0x52, 0x56, 0x60, 0x79,
		0x0a, 0x01, 0x60, 0x43, 0x49, 0x52, 0x45, 0xa1,
		0x08, 0x70, 0x0a, 0x00, 0x43, 0x49, 0x52, 0x45,
		0xa4, 0x43, 0x42, 0x30, 0x35, 0x14, 0x0d, 0x5f,
		0x44, 0x49, 0x53, 0x00, 0x70, 0x0a, 0x80, 0x50,
		0x49, 0x52, 0x45, 0x14, 0x1b, 0x5f, 0x53, 0x52,
		0x53, 0x01, 0x8b, 0x68, 0x0a, 0x01, 0x53, 0x49,
		0x52, 0x45, 0x82, 0x53, 0x49, 0x52, 0x45, 0x60,
		0x70, 0x76, 0x60, 0x50, 0x49, 0x52, 0x45, 0x5b,
		0x82, 0x4f, 0x0a, 0x4c, 0x4e, 0x4b, 0x46, 0x08,
		0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0c,
		0x0f, 0x08, 0x5f, 0x55, 0x49, 0x44, 0x0a, 0x06,
		0x14, 0x18, 0x5f, 0x53, 0x54, 0x41, 0x00, 0xa0,
		0x0c, 0x50, 0x49, 0x52, 0x56, 0x50, 0x49, 0x52,
		0x46, 0xa4, 0x0a, 0x0b, 0xa1, 0x04, 0xa4, 0x0a,
		0x09, 0x08, 0x5f, 0x50, 0x52, 0x53, 0x11, 0x09,
		0x0a, 0x06, 0x23, 0xf8, 0xde, 0x18, 0x79, 0x00,
		0x08, 0x43, 0x42, 0x30, 0x36, 0x11, 0x09, 0x0a,
		0x06, 0x23, 0x00, 0x00, 0x18, 0x79, 0x00, 0x8b,
		0x43, 0x42, 0x30, 0x36, 0x0a, 0x01, 0x43, 0x49,
		0x52, 0x46, 0x14, 0x2b, 0x5f, 0x43, 0x52, 0x53,
		0x00, 0x7b, 0x50, 0x49, 0x52, 0x46, 0x0a, 0x8f,
		0x60, 0xa0, 0x0e, 0x50, 0x49, 0x52, 0x56, 0x60,
		0x79, 0x0a, 0x01, 0x60, 0x43, 0x49, 0x52, 0x46,
		0xa1, 0x08, 0x70, 0x0a, 0x00, 0x43, 0x49, 0x52,
		0x46, 0xa4, 0x43, 0x42, 0x30, 0x36, 0x14, 0x0d,
		0x5f, 0x44, 0x49, 0x53, 0x00, 0x70, 0x0a, 0x80,
		0x50, 0x49, 0x52, 0x46, 0x14, 0x1b, 0x5f, 0x53,
		0x52, 0x53, 0x01, 0x8b, 0x68, 0x0a, 0x01, 0x53,
		0x49, 0x52, 0x46, 0x82, 0x53, 0x49, 0x52, 0x46,
		0x60, 0x70, 0x76, 0x60, 0x50, 0x49, 0x52, 0x46,
		0x5b, 0x82, 0x4f, 0x0a, 0x4c, 0x4e, 0x4b, 0x47,
		0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0,
		0x0c, 0x0f, 0x08, 0x5f, 0x55, 0x49, 0x44, 0x0a,
		0x07, 0x14, 0x18, 0x5f, 0x53, 0x54, 0x41, 0x00,
		0xa0, 0x0c, 0x50, 0x49, 0x52, 0x56, 0x50, 0x49,
		0x52, 0x47, 0xa4, 0x0a, 0x0b, 0xa1, 0x04, 0xa4,
		0x0a, 0x09, 0x08, 0x5f, 0x50, 0x52, 0x53, 0x11,
		0x09, 0x0a, 0x06, 0x23, 0xf8, 0xde, 0x18, 0x79,
		0x00, 0x08, 0x43, 0x42, 0x30, 0x37, 0x11, 0x09,
		0x0a, 0x06, 0x23, 0x00, 0x00, 0x18, 0x79, 0x00,
		0x8b, 0x43, 0x42, 0x30, 0x37, 0x0a, 0x01, 0x43,
		0x49, 0x52, 0x47, 0x14, 0x2b, 0x5f, 0x43, 0x52,
		0x53, 0x00, 0x7b, 0x50, 0x49, 0x52, 0x47, 0x0a,
		0x8f, 0x60, 0xa0, 0x0e, 0x50, 0x49, 0x52, 0x56,
		0x60, 0x79, 0x0a, 0x01, 0x60, 0x43, 0x49, 0x52,
		0x47, 0xa1, 0x08, 0x70, 0x0a, 0x00, 0x43, 0x49,
		0x52, 0x47, 0xa4, 0x43, 0x42, 0x30, 0x37, 0x14,
		0x0d, 0x5f, 0x44, 0x49, 0x53, 0x00, 0x70, 0x0a,
		0x80, 0x50, 0x49, 0x52, 0x47, 0x14, 0x1b, 0x5f,
		0x53, 0x52, 0x53, 0x01, 0x8b, 0x68, 0x0a, 0x01,
		0x53, 0x49, 0x52, 0x47, 0x82, 0x53, 0x49, 0x52,
		0x47, 0x60, 0x70, 0x76, 0x60, 0x50, 0x49, 0x52,
		0x47, 0x5b, 0x82, 0x4f, 0x0a, 0x4c, 0x4e, 0x4b,
		0x48, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41,
		0xd0, 0x0c, 0x0f, 0x08, 0x5f, 0x55, 0x49, 0x44,
		0x0a, 0x08, 0x14, 0x18, 0x5f, 0x53, 0x54, 0x41,
		0x00, 0xa0, 0x0c, 0x50, 0x49, 0x52, 0x56, 0x50,
		0x49, 0x52, 0x48, 0xa4, 0x0a, 0x0b, 0xa1, 0x04,
		0xa4, 0x0a, 0x09, 0x08, 0x5f, 0x50, 0x52, 0x53,
		0x11, 0x09, 0x0a, 0x06, 0x23, 0xf8, 0xde, 0x18,
		0x79, 0x00, 0x08, 0x43, 0x42, 0x30, 0x38, 0x11,
		0x09, 0x0a, 0x06, 0x23, 0x00, 0x00, 0x18, 0x79,
		0x00, 0x8b, 0x43, 0x42, 0x30, 0x38, 0x0a, 0x01,
		0x43, 0x49, 0x52, 0x48, 0x14, 0x2b, 0x5f, 0x43,
		0x52, 0x53, 0x00, 0x7b, 0x50, 0x49, 0x52, 0x48,
		0x0a, 0x8f, 0x60, 0xa0, 0x0e, 0x50, 0x49, 0x52,
		0x56, 0x60, 0x79, 0x0a, 0x01, 0x60, 0x43, 0x49,
		0x52, 0x48, 0xa1, 0x08, 0x70, 0x0a, 0x00, 0x43,
		0x49, 0x52, 0x48, 0xa4, 0x43, 0x42, 0x30, 0x38,
		0x14, 0x0d, 0x5f, 0x44, 0x49, 0x53, 0x00, 0x70,
		0x0a, 0x80, 0x50, 0x49, 0x52, 0x48, 0x14, 0x1b,
		0x5f, 0x53, 0x52, 0x53, 0x01, 0x8b, 0x68, 0x0a,
		0x01, 0x53, 0x49, 0x52, 0x48, 0x82, 0x53, 0x49,
		0x52, 0x48, 0x60, 0x70, 0x76, 0x60, 0x50, 0x49,
		0x52, 0x48, 0x5b, 0x82, 0x48, 0x07, 0x53, 0x49,
		0x4f, 0x5f, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c,
		0x41, 0xd0, 0x0c, 0x02, 0x08, 0x5f, 0x43, 0x52,
		0x53, 0x11, 0x42, 0x06, 0x0a, 0x5e, 0x47, 0x01,
		0x60, 0x00, 0x60, 0x00, 0x01, 0x01, 0x47, 0x01,
		0x64, 0x00, 0x64, 0x00, 0x01, 0x01, 0x47, 0x01,
		0x20, 0x02, 0x20, 0x02, 0x01, 0x04, 0x47, 0x01,
		0x24, 0x02, 0x24, 0x02, 0x01, 0x04, 0x86, 0x09,
		0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
		0x00, 0x10, 0x47, 0x01, 0xd0, 0x04, 0xd0, 0x04,
		0x01, 0x02, 0x47, 0x01, 0x61, 0x00, 0x61, 0x00,
		0x01, 0x01, 0x47, 0x01, 0x00, 0x04, 0x00, 0x04,
		0x01, 0x08, 0x47, 0x01, 0xb2, 0x00, 0xb2, 0x00,
		0x01, 0x01, 0x47, 0x01, 0x84, 0x00, 0x84, 0x00,
		0x01, 0x01, 0x47, 0x01, 0x72, 0x00, 0x72, 0x00,
		0x01, 0x06, 0x79, 0x00, 0x5b, 0x82, 0x2c, 0x43,
		0x4f, 0x4d, 0x31, 0x08, 0x5f, 0x48, 0x49, 0x44,
		0x0c, 0x41, 0xd0, 0x05, 0x01, 0x08, 0x5f, 0x55,
		0x49, 0x44, 0x0a, 0x01, 0x08, 0x5f, 0x43, 0x52,
		0x53, 0x11, 0x10, 0x0a, 0x0d, 0x47, 0x01, 0xf8,
		0x03, 0xf8, 0x03, 0x01, 0x08, 0x22, 0x10, 0x00,
		0x79, 0x00, 0x5b, 0x82, 0x2c, 0x43, 0x4f, 0x4d,
		0x32, 0x08, 0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41,
		0xd0, 0x05, 0x01, 0x08, 0x5f, 0x55, 0x49, 0x44,
		0x0a, 0x02, 0x08, 0x5f, 0x43, 0x52, 0x53, 0x11,
		0x10, 0x0a, 0x0d, 0x47, 0x01, 0xf8, 0x02, 0xf8,
		0x02, 0x01, 0x08, 0x22, 0x08, 0x00, 0x79, 0x00,
		0x5b, 0x82, 0x25, 0x52, 0x54, 0x43, 0x5f, 0x08,
		0x5f, 0x48, 0x49, 0x44, 0x0c, 0x41, 0xd0, 0x0b,
		0x00, 0x08, 0x5f, 0x43, 0x52, 0x53, 0x11, 0x10,
		0x0a, 0x0d, 0x47, 0x01, 0x70, 0x00, 0x70, 0x00,
		0x01, 0x02, 0x22, 0x00, 0x01, 0x79, 0x00, 0x5b,
		0x82, 0x2b, 0x50, 0x49, 0x43, 0x5f, 0x08, 0x5f,
		0x48, 0x49, 0x44, 0x0b, 0x41, 0xd0, 0x08, 0x5f,
		0x43, 0x52, 0x53, 0x11, 0x18, 0x0a, 0x15, 0x47,
		0x01, 0x20, 0x00, 0x20, 0x00, 0x01, 0x02, 0x47,
		0x01, 0xa0, 0x00, 0xa0, 0x00, 0x01, 0x02, 0x22,
		0x04, 0x00, 0x79, 0x00, 0x5b, 0x82, 0x25, 0x54,
		0x49, 0x4d, 0x52, 0x08, 0x5f, 0x48, 0x49, 0x44,
		0x0c, 0x41, 0xd0, 0x01, 0x00, 0x08, 0x5f, 0x43,
		0x52, 0x53, 0x11, 0x10, 0x0a, 0x0d, 0x47, 0x01,
		0x40, 0x00, 0x40, 0x00, 0x01, 0x04, 0x22, 0x01,
		0x00, 0x79, 0x00, 0x10, 0x39, 0x2e, 0x5f, 0x53,
		0x42, 0x5f, 0x50, 0x43, 0x30, 0x30, 0x5b, 0x82,
		0x2d, 0x48, 0x50, 0x45, 0x54, 0x08, 0x5f, 0x48,
		0x49, 0x44, 0x0c, 0x41, 0xd0, 0x01, 0x03, 0x08,
		0x5f, 0x55, 0x49, 0x44, 0x0a, 0x00, 0x08, 0x5f,
		0x43, 0x52, 0x53, 0x11, 0x11, 0x0a, 0x0e, 0x86,
		0x09, 0x00, 0x01, 0x00, 0x00, 0xd0, 0xfe, 0x00,
		0x04, 0x00, 0x00, 0x79
	};

	dsdt = (void *) (((uintptr_t) tb) + DSDT_OFFSET);
	/* copy DSDT template to guest memory */
	memcpy(dsdt, dsdt_tmpl, 2604);

	pci_write_dsdt();

	/* write checksum */
	acpitbl_write8(dsdt, 0x9, acpitbl_checksum(dsdt, 2604));
}

int
acpi_build(int ncpu)
{
	int err;

	acpi_ncpu = ncpu;
	tb = paddr_guest2host(XHYVE_ACPI_BASE, XHYVE_ACPI_SIZE);
	if (tb == NULL) {
		return (EFAULT);
	}

	err = xh_vm_get_hpet_capabilities(&hpet_capabilities);
	if (err != 0) {
		return (err);
	}

	acpitbl_build_rdsp();
	acpitbl_build_rsdt();
	acpitbl_build_xsdt();
	acpitbl_build_madt();
	acpitbl_build_fadt();
	acpitbl_build_hpet();
	acpitbl_build_mcfg();
	acpitbl_build_facs();
	acpitbl_build_dsdt();

	return 0;
}
